/*
 * Copyright 2023-2025, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * 龙芯LoongArch64架构定时器实现
 * 本文件实现龙芯平台的定时器和实时时钟功能
 */

#include <KernelExport.h>

#include <arch/timer.h>
#include <boot/kernel_args.h>
#include <kernel.h>
#include <debug.h>
#include <timer.h>
#include <int.h>
#include <real_time_clock.h>
#include <real_time_data.h>

// 定义调试输出宏
#define TRACE_TIMER
#ifdef TRACE_TIMER
#define TRACE(x...) dprintf("arch_timer_loongson: " x)
#else
#define TRACE(x...) ;
#endif

// 龙芯平台定时器相关常量
#define LOONGSON_STABLE_COUNTER_FREQ 100000000 // 稳定计数器频率（100MHz）

// 定时器CSR寄存器地址
#define CSR_TMID 0x40 // 定时器ID
#define CSR_TCFG 0x41 // 定时器配置
#define CSR_TVAL 0x42 // 定时器初值
#define CSR_CNTC 0x43 // 计数器补偿值
#define CSR_TICLR 0x44 // 定时器中断清除

// 定时器配置位
#define TCFG_EN (1ULL << 0)     // 定时器使能
#define TCFG_PERIOD (1ULL << 1) // 周期性模式
#define TCFG_INT_EN (1ULL << 2) // 中断使能

// 定时器中断号
#define TIMER_IRQ 11

// 全局变量
static uint64 sTimerFrequency = LOONGSON_STABLE_COUNTER_FREQ;
static uint64 sTimerMax = 0xffffffffffffffffULL;
static uint64 sTimerConversionFactor = 0;
static uint64 sTimerHiMax = 0;

// 读取CSR寄存器
static inline uint64
read_csr(uint32 reg)
{
    uint64 val;
    asm volatile("csrrd %0, %1" : "=r"(val) : "i"(reg));
    return val;
}

// 写入CSR寄存器
static inline void
write_csr(uint32 reg, uint64 val)
{
    asm volatile("csrwr %0, %1" : : "r"(val), "i"(reg));
}

// 获取当前计数器值
static uint64
get_timer_value(void)
{
    return read_csr(CSR_TVAL);
}

// 设置硬件定时器
void
loongson_set_hardware_timer(bigtime_t timeout)
{
    // 将微秒转换为定时器计数值
    uint64 ticks = (static_cast<__uint128_t>(timeout) * sTimerFrequency) / 1000000;
    
    // 确保不超过最大值
    if (ticks > sTimerMax)
        ticks = sTimerMax;
    
    // 清除定时器中断
    write_csr(CSR_TICLR, 1);
    
    // 设置定时器初值
    write_csr(CSR_TVAL, ticks);
    
    // 配置并启用定时器（单次模式）
    write_csr(CSR_TCFG, TCFG_EN | TCFG_INT_EN);
    
    TRACE("Set hardware timer: %" B_PRId64